import type { AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from "axios"
import axios from "axios"
import { CustomAxiosRequestConfig, CustomCreateAxiosDefaults } from "./axiosTransform"
import { AxiosCanceler } from "./axiosCancel"
import { isFunction } from "@/utils"

export class VAxios {
    private instance: AxiosInstance
    private options: CustomCreateAxiosDefaults

    constructor(options: CustomCreateAxiosDefaults) {
        this.options = options
        this.instance = axios.create(options)
        this.setupInterceptors()
    }

    /**
     * @description:  创建axios实例
     */
    private createAxios(config: CustomCreateAxiosDefaults): void {
        this.instance = axios.create(config)
    }

    /**
     * @description: 重新配置axios
     */
    configAxios(config: CustomCreateAxiosDefaults) {
        if (!this.instance) {
            return
        }
        this.createAxios(config)
    }

    getAxios(): AxiosInstance {
        return this.instance
    }

    getDefaultOptions(): CustomCreateAxiosDefaults {
        return this.options
    }

    /**
     * @description: 设置通用header
     */
    setHeader(headers: any): void {
        if (!this.instance) {
            return
        }
        Object.assign(this.instance.defaults.headers, headers)
    }

    // 配置拦截器
    private setupInterceptors() {
        const { transform } = this.options
        if (!transform) {
            return
        }
        const { requestInterceptors, requestInterceptorsCatch, responseInterceptors, responseInterceptorsCatch } = transform
        const axiosCanceler = new AxiosCanceler()

        // 请求拦截器配置处理
        this.getAxios().interceptors.request.use((config: InternalAxiosRequestConfig & CustomAxiosRequestConfig) => {
            const ignoreCancelToken = config.requestOptions?.ignoreCancelToken
            !ignoreCancelToken && axiosCanceler.addPending(config)
            requestInterceptors && isFunction(requestInterceptors) && requestInterceptors(config, config.requestOptions ?? {})
            return config
        }, undefined)

        // 请求拦截器错误捕获
        requestInterceptorsCatch &&
            isFunction(requestInterceptorsCatch) &&
            this.getAxios().interceptors.request.use(undefined, requestInterceptorsCatch)

        // 响应结果拦截器处理
        this.getAxios().interceptors.response.use((res: AxiosResponse<any>) => {
            res && axiosCanceler.removePending(res.config)
            if (responseInterceptors && isFunction(responseInterceptors)) {
                res = responseInterceptors(res)
            }
            return res
        }, undefined)

        // 响应结果拦截器错误捕获
        responseInterceptorsCatch &&
            isFunction(responseInterceptorsCatch) &&
            this.getAxios().interceptors.response.use(undefined, responseInterceptorsCatch)
    }
}
